package cn.com.anypay.manager.payment.factory;

import cn.com.anypay.manager.payment.core.IPaymentProduct;
import cn.com.anypay.manager.payment.core.PaymentProductException;
import cn.com.anypay.manager.payment.dto.ProductConfigDTO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 支付产品工厂 - 不再实现InitializingBean
 * 由PaymentManager统一管理生命周期
 *
 * 使用工厂模式管理支付产品的创建、注册和获取
 * 支持按渠道和产品类型获取产品实例
 *
 * @author AnyPay Team
 * @version 1.0
 * @since 2025-07-05
 */
public class PaymentProductFactory {  // 移除 @Component 和 InitializingBean

    private static final Logger logger = LoggerFactory.getLogger(PaymentProductFactory.class);

    /**
     * 产品实例缓存
     * Key: channelId_productType, Value: IPaymentProduct实例
     */
    private final Map<String, IPaymentProduct> productCache = new ConcurrentHashMap<>();

    /**
     * 渠道支持的产品类型映射
     * Key: channelId, Value: Set of productTypes
     */
    private final Map<String, Set<String>> channelProductMap = new ConcurrentHashMap<>();

    /**
     * 产品配置映射
     * Key: channelId_productType, Value: ProductConfigDTO
     */
    private final Map<String, ProductConfigDTO> productConfigMap = new ConcurrentHashMap<>();

    /**
     * 初始化状态
     */
    private volatile boolean initialized = false;

    /**
     * 手动初始化方法 - 替代InitializingBean
     */
    public void initialize() {
        if (initialized) {
            logger.warn("PaymentProductFactory already initialized");
            return;
        }

        logger.info("=== 支付产品工厂初始化 ===");
        // 不再自动注册产品，等待渠道注册
        initialized = true;
        logger.info("支付产品工厂初始化完成，等待渠道注册产品");
    }

    /**
     * 销毁方法
     */
    public void destroy() {
        logger.info("=== 支付产品工厂销毁 ===");

        // 销毁所有产品
        for (IPaymentProduct product : productCache.values()) {
            try {
                product.destroy();
            } catch (Exception e) {
                logger.error("销毁产品失败", e);
            }
        }

        productCache.clear();
        channelProductMap.clear();
        productConfigMap.clear();
        initialized = false;

        logger.info("支付产品工厂销毁完成");
    }

    /**
     * 获取支付产品实例
     *
     * @param channelId   渠道ID
     * @param productType 产品类型
     * @return 支付产品实例
     * @throws PaymentProductException 获取失败时抛出
     */
    public IPaymentProduct createProduct(String channelId, String productType) throws PaymentProductException {
        String key = generateKey(channelId, productType);

        IPaymentProduct product = productCache.get(key);
        if (product == null) {
            throw new PaymentProductException("PRODUCT_NOT_FOUND",
                String.format("Product not found: channel=%s, type=%s", channelId, productType),
                channelId, productType);
        }

        // 检查产品是否可用
        if (!product.isAvailable()) {
            throw new PaymentProductException("PRODUCT_UNAVAILABLE",
                String.format("Product is not available: channel=%s, type=%s", channelId, productType),
                channelId, productType);
        }

        logger.debug("获取支付产品: channel={}, type={}, product={}",
            channelId, productType, product.getClass().getSimpleName());

        return product;
    }

    /**
     * 通过渠道注册产品（新增方法）
     *
     * @param channelId   渠道ID
     * @param implementationId 实现ID
     * @param productType 产品类型
     * @param product     产品实例
     */
    public void registerProductByChannel(String channelId, String implementationId, String productType, IPaymentProduct product) {
        String key = generateKey(channelId, productType);

        try {
            // 初始化产品
            if (!product.isInitialized()) {
                product.initialize();
            }

            productCache.put(key, product);

            // 更新渠道产品映射
            channelProductMap.computeIfAbsent(channelId, k -> new HashSet<>()).add(productType);

            // 保存产品配置
            if (product.getProductConfig() != null) {
                productConfigMap.put(key, product.getProductConfig());
            }

            logger.debug("注册支付产品成功: c={}, t={}, i={}, p={}",
                channelId, productType, implementationId, product.getClass().getSimpleName());

        } catch (Exception e) {
            logger.error("注册支付产品失败: channel={}, type={}, impl={}", channelId, productType, implementationId, e);
        }
    }

    /**
     * 取消注册支付产品
     *
     * @param channelId   渠道ID
     * @param productType 产品类型
     */
    public void unregisterProduct(String channelId, String productType) {
        String key = generateKey(channelId, productType);

        IPaymentProduct product = productCache.remove(key);
        if (product != null) {
            try {
                product.destroy();
            } catch (Exception e) {
                logger.error("销毁产品失败: channel={}, type={}", channelId, productType, e);
            }
        }

        // 更新渠道产品映射
        Set<String> productTypes = channelProductMap.get(channelId);
        if (productTypes != null) {
            productTypes.remove(productType);
            if (productTypes.isEmpty()) {
                channelProductMap.remove(channelId);
            }
        }

        // 移除产品配置
        productConfigMap.remove(key);

        logger.info("取消注册支付产品: channel={}, type={}", channelId, productType);
    }

    /**
     * 获取渠道支持的产品类型
     *
     * @param channelId 渠道ID
     * @return 产品类型数组，按字母顺序排序
     */
    public String[] getSupportedProductTypes(String channelId) {
        Set<String> productTypes = channelProductMap.get(channelId);
        if (productTypes == null || productTypes.isEmpty()) {
            logger.debug("渠道 {} 暂无注册的支付产品", channelId);
            return new String[0];
        }

        // 转换为数组并排序，确保顺序一致
        String[] result = productTypes.toArray(new String[0]);
        java.util.Arrays.sort(result);

        logger.debug("渠道 {} 支持的支付产品: {}", channelId, java.util.Arrays.toString(result));
        return result;
    }

    /**
     * 获取所有已注册的渠道
     *
     * @return 渠道ID数组
     */
    public String[] getAllChannels() {
        return channelProductMap.keySet().toArray(new String[0]);
    }

    /**
     * 获取所有已注册的产品信息
     *
     * @return 产品信息列表
     */
    public List<Map<String, Object>> getAllProducts() {
        return productCache.entrySet().stream()
            .map(entry -> {
                IPaymentProduct product = entry.getValue();
                Map<String, Object> info = new HashMap<>();
                info.put("key", entry.getKey());
                info.put("channelId", extractChannelId(entry.getKey()));
                info.put("productType", product.getProductType());
                info.put("productName", product.getProductName());
                info.put("productVersion", product.getProductVersion());
                info.put("isAvailable", product.isAvailable());
                info.put("supportedFeatures", product.getSupportedFeatures());
                info.put("className", product.getClass().getSimpleName());
                return info;
            })
            .collect(Collectors.toList());
    }

    /**
     * 检查产品是否存在
     *
     * @param channelId   渠道ID
     * @param productType 产品类型
     * @return 是否存在
     */
    public boolean hasProduct(String channelId, String productType) {
        String key = generateKey(channelId, productType);
        return productCache.containsKey(key);
    }

    /**
     * 获取产品配置
     *
     * @param channelId   渠道ID
     * @param productType 产品类型
     * @return 产品配置
     */
    public ProductConfigDTO getProductConfig(String channelId, String productType) {
        String key = generateKey(channelId, productType);
        return productConfigMap.get(key);
    }

    /**
     * 更新产品配置
     *
     * @param channelId   渠道ID
     * @param productType 产品类型
     * @param config      新配置
     */
    public void updateProductConfig(String channelId, String productType, ProductConfigDTO config) {
        String key = generateKey(channelId, productType);

        IPaymentProduct product = productCache.get(key);
        if (product != null) {
            product.setProductConfig(config);
            productConfigMap.put(key, config);
            logger.info("更新产品配置: channel={}, type={}", channelId, productType);
        }
    }

    /**
     * 获取工厂统计信息
     *
     * @return 统计信息
     */
    public Map<String, Object> getFactoryStatistics() {
        Map<String, Object> stats = new HashMap<>();
        stats.put("totalProducts", productCache.size());
        stats.put("totalChannels", channelProductMap.size());
        stats.put("channelProductMap", new HashMap<>(channelProductMap));

        // 按渠道统计产品数量
        Map<String, Integer> channelStats = channelProductMap.entrySet().stream()
            .collect(Collectors.toMap(
                Map.Entry::getKey,
                entry -> entry.getValue().size()
            ));
        stats.put("productCountByChannel", channelStats);

        // 可用产品统计
        long availableCount = productCache.values().stream()
            .mapToLong(product -> product.isAvailable() ? 1 : 0)
            .sum();
        stats.put("availableProducts", availableCount);
        stats.put("unavailableProducts", productCache.size() - availableCount);

        return stats;
    }

    /**
     * 生成缓存键
     */
    private String generateKey(String channelId, String productType) {
        return channelId + "_" + productType;
    }

    /**
     * 从键中提取渠道ID
     */
    private String extractChannelId(String key) {
        int index = key.indexOf('_');
        return index > 0 ? key.substring(0, index) : key;
    }
}